package com.lagou.demo.config;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.StringReader;
import java.util.Properties;

/**
 * @Description zookeeper客户端连接
 * @Author 郭汝诚
 * @Date 2020/7/26 13:07
 * @Version 1.0
 **/
@Component
public class ZkClient {

    @Value("${dataSourcePath}")
    private String dataSourcePath;

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public CuratorFramework curatorFramework() throws Exception {
        //创建zk客户端连接
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("127.0.0.1:2181")
                .sessionTimeoutMs(50000)
                .connectionTimeoutMs(30000)
                .retryPolicy(retryPolicy)
                .namespace("data-source")
                .build();
        client.start();

        //对数据源配置节点信息注册监听
        NodeCache cache = new NodeCache(client,dataSourcePath,true);
        NodeCacheListener listener = new NodeCacheListener() {
            //当节点信息发生变化时，触发节点变化通知
            @Override
            public void nodeChanged() throws Exception {
                ChildData currentData = cache.getCurrentData();
                //删除已注册的数据源bean
                DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
                beanFactory.removeBeanDefinition("dataSource");

                //读取最新配置信息
                String context = new String(currentData.getData());
                Properties properties = new Properties();
                properties.load(new StringReader(context));

                //创建bean信息
                BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DataSource.class);
                beanDefinitionBuilder.addPropertyValue("jdbcUrl",properties.getProperty("url"));
                beanDefinitionBuilder.addPropertyValue("username",properties.getProperty("username"));
                beanDefinitionBuilder.addPropertyValue("password",properties.getProperty("password"));
                beanDefinitionBuilder.addPropertyValue("driverClass",properties.getProperty("driver-class-name"));
                //动态注册bean.
                beanFactory.registerBeanDefinition("dataSource", beanDefinitionBuilder.getBeanDefinition());
            }
        };
        //启动监听
        cache.getListenable().addListener(listener);
        cache.start();
        return client;
    }

}
